﻿using CocoaAni.Net.WebSockets.Exceptions;
using System.Text;

namespace CocoaAni.Net.WebSockets.Tools;

public class WSHandShakeRequest : WSHttpHeadersHandler
{
    public string Method { get; set; } = "GET";
    public string Url { get; set; } = "/";
    public string ProtocolVersion { get; set; } = "HTTP/1.1";
    public Memory<byte>? Body { get; set; }

    public WSHandShakeRequest()
    {
    }

    public WSHandShakeRequest Parse(byte[] data, int count)
    {
        var headerEndIdx = WSNetUtils.GetHttpHeaderEndIndex(data);
        if (headerEndIdx == -1)
        {
            throw new FormatException($"Http Request Is Not Has Double New Line!");
        }
        var requestHeader = Encoding.UTF8.GetString(data, 0, headerEndIdx).Split("\r\n");
        var requestHeaderLine = requestHeader[0].Trim();
        var requestHeaderLineData = requestHeaderLine.Split(' ');
        if (requestHeaderLineData.Length < 3)
        {
            throw new FormatException($"Http Request Request Line Format Error => [{requestHeaderLine}]");
        }
        Method = requestHeaderLineData[0];
        Url = requestHeaderLineData[1];
        ProtocolVersion = requestHeaderLineData[2];
        var headers = Headers;
        Headers = WSNetUtils.ParseHeaders(requestHeader[1..], ref headers);
        if (headerEndIdx == data.Length - 1) return this;
        Body = data.AsMemory(headerEndIdx..count);
        return this;
    }

    public byte[] Build()
    {
        var requestLine = $"{Method} {Url} {ProtocolVersion}";
        var sb = new StringBuilder();
        sb.Append(requestLine).AppendLine();
        foreach (var (key, value) in Headers)
        {
            switch (value)
            {
                case string strValue:
                    sb.Append($"{key}: {value}{Environment.NewLine}");
                    break;

                case IEnumerable<string> values:
                    {
                        sb.Append(key).Append(": ");
                        foreach (var s in values)
                        {
                            sb.AppendLine($"{s}; {Environment.NewLine}");
                        }
                        break;
                    }
            }
        }
        sb.AppendLine();
        sb.AppendLine();
        return Encoding.UTF8.GetBytes(sb.ToString());
    }

    public WSHandShakeResponse CreateOkResponse()
    {
        var key = GetHeaderValue("Sec-WebSocket-Key");
        if (key == null)
        {
            throw new WebSocketException("HeaderBuffer Not Found => Sec-WebSocket-Key");
        }
        return WSHandShakeResponse.CreateOk(key);
    }

    public WSHandShakeResponse CreateErrorResponse()
    {
        throw new NotImplementedException();
    }
}